package com.bjpowerndoe.ylb.web.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bjpowerndoe.ylb.common.AppConsts;
import com.bjpowerndoe.ylb.common.RedisKey;
import com.bjpowerndoe.ylb.domain.FinanceAccountPO;
import com.bjpowerndoe.ylb.domain.UserPO;
import com.bjpowerndoe.ylb.map.UserAccountMap;
import com.bjpowerndoe.ylb.mapper.FinanceAccountMapper;
import com.bjpowerndoe.ylb.mapper.UserMapper;
import com.bjpowerndoe.ylb.web.config.RealnameConfig;
import com.bjpowerndoe.ylb.web.enums.CodeEnum;
import com.bjpowerndoe.ylb.web.model.dto.UserDTO;
import com.bjpowerndoe.ylb.web.service.inter.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 *
 */
@RequiredArgsConstructor
@Service
public class UserServiceImpl implements UserService {

    private final  StringRedisTemplate stringRedisTemplate;
    private final UserMapper userMapper;
    private final FinanceAccountMapper accountMapper;

    private final RealnameConfig realnameConfig;

    @Value("${secret.salt}")
    private String secretSalt;

    @Override
    public boolean checkSmsCode(String action, String phone, String code) {
        boolean check = false;
        String key = "";
        if(AppConsts.SMS_ACTION_REGISTER.equalsIgnoreCase(action)){
            //验证注册的验证码
            key  = RedisKey.SMS_REGISTER_CODE + phone;
            String codeRedis = stringRedisTemplate.opsForValue().get(key);
            if( code.equals(codeRedis)){
                check = true;
            }
        } else if(AppConsts.SMS_ACTION_LOGIN.equalsIgnoreCase(action)){
            //登录
            key  = RedisKey.SMS_LOGIN_CODE + phone;
            String codeRedis = stringRedisTemplate.opsForValue().get(key);
            if( code.equals(codeRedis)){
                check = true;
            }
        }

        return check;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public synchronized CodeEnum userRegister(String phone, String secret) {
        CodeEnum code = CodeEnum.FAIL;
        //检查手机号是否注册过
        UserPO user = userMapper.selectOne(new QueryWrapper<UserPO>().eq("phone", phone) );
        if( user == null ){ //手机号没有注册过
            //二次加密-密码     secret + secretSalt;
            String newSecret = DigestUtil.md5Hex(secret + secretSalt);//md5

            UserPO addUser = new UserPO();
            addUser.setPhone(phone);
            addUser.setLoginPassword(newSecret);
            addUser.setAddTime(new Date());
            userMapper.insert(addUser);

            //添加资金账号
            FinanceAccountPO account = new FinanceAccountPO();
            account.setUid(addUser.getId());
            account.setAvailableMoney(new BigDecimal("88"));
            accountMapper.insert(account);
            code = CodeEnum.OK;

        } else  { //手机号已经注册
            code = CodeEnum.PHONE_REGISTER_USE;
        }
        return code;
    }

    //登录用户
    @Override
    public UserDTO userLogin(String phone, String secret) {

        UserDTO userDTO = null;
        //二次加密-密码     secret + secretSalt;
        String newSecret = DigestUtil.md5Hex(secret + secretSalt);//md5
        UserPO user = userMapper.selectOne(new QueryWrapper<UserPO>()
                .eq("phone", phone)
                .eq("login_password", newSecret) );

        if(user != null){ //用户存在
            //更新用户的登录时间
            user.setLastLoginTime(new Date());
            userMapper.updateById(user);
            //转为DTO
            userDTO = BeanUtil.copyProperties(user,UserDTO.class);
        }

        return userDTO;
    }

    @Override
    public boolean saveTokenToRedis(UserDTO userDTO, String token) {
        //使用Hash类型存储多个数据
        String key = RedisKey.TOKEN_LOGIN + token.toUpperCase();

        Map<String,String> data = new HashMap<>();
        data.put("uid",String.valueOf(userDTO.getId()));
        data.put("phone", userDTO.getPhone());
        data.put("datetime", DateUtil.format(new Date(),"yyyy-MM-dd HH:mm:ss"));

        stringRedisTemplate.opsForHash().putAll(key,data);

        return stringRedisTemplate.hasKey(key);
    }

    @Override
    public UserDTO queryUserById(Integer uid) {
        UserPO userPO = userMapper.selectById(uid);
        return BeanUtil.copyProperties(userPO,UserDTO.class);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public synchronized boolean userRealname(Integer uid, String name, String idCard) {

        Map<String,Object> param = new HashMap<>();
        param.put("cardNo",idCard);
        param.put("realName",name);
        param.put("appkey",realnameConfig.getAppkey());

        Boolean bool = null;
        try{
            //String response = HttpUtil.get(realnameConfig.getUrl(), param, 6000);
            String response = "{\n" +
                    "    \"code\": \"10000\",\n" +
                    "    \"charge\": false,\n" +
                    "    \"remain\": 1305,\n" +
                    "    \"msg\": \"查询成功\",\n" +
                    "    \"result\": {\n" +
                    "        \"error_code\": 0,\n" +
                    "        \"reason\": \"成功\",\n" +
                    "        \"result\": {\n" +
                    "            \"realname\": \""+name+"\",\n" +
                    "            \"idcard\": \"350721197702134399\",\n" +
                    "            \"isok\": true\n" +
                    "        }\n" +
                    "    }\n" +
                    "}";
            if( StrUtil.isNotBlank(response) ){
                JSONObject obj = JSONUtil.parseObj(response);
                if("10000".equals(obj.getStr("code"))){
                    bool = obj.getJSONObject("result").getJSONObject("result").getBool("isok");
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }

        //判断是否成功
        if( bool != null && bool ){
            //认证成功，更新数据库
            UserPO userPO = new UserPO();
            userPO.setId(uid);
            userPO.setName(name);
            userPO.setIdCard(idCard);
            int i = userMapper.updateById(userPO);
            if( i < 1 ){
                throw new RuntimeException("实名认证，更新数据库失败!");
            }
        }
        //调用第三方接口
        return bool == null ? false: bool.booleanValue();
    }

    @Override
    public UserAccountMap queryUserAccountByUid(Integer uid) {
        return userMapper.selectUserAccountByUid(uid);
    }
}
